<template>
  <a-spin :spinning="loading" wrapper-class-name="city-select-row">
    <a-select
      v-model:value="state.province"
      :disabled="disabled"
      show-search
      :allow-clear="allowClear"
      class="item"
      option-filter-prop="title"
      placeholder="请选择省"
      v-bind="provinceProps"
      @change="selectProvince"
    >
      <a-select-option v-for="item in provinceList" :key="item.code" :title="item.name">
        {{ item.name }}
      </a-select-option>
    </a-select>
    <a-select
      v-model:value="state.city"
      :disabled="disabled || !state.province"
      show-search
      :allow-clear="allowClear"
      class="item"
      option-filter-prop="title"
      placeholder="请选择市"
      v-bind="cityProps"
      @change="selectCity"
    >
      <a-select-option v-for="item in cityList" :key="item.code" :title="item.name">
        {{ item.name }}
      </a-select-option>
    </a-select>
    <a-select
      v-model:value="state.district"
      :disabled="disabled || !state.city"
      show-search
      :allow-clear="allowClear"
      class="item"
      option-filter-prop="title"
      placeholder="请选择区"
      v-bind="districtProps"
      @change="selectDistrict"
    >
      <a-select-option v-for="item in districtList" :key="item.code" :title="item.name">
        {{ item.name }}
      </a-select-option>
    </a-select>
  </a-spin>
</template>

<script lang="ts">
import { defineComponent, computed, reactive, watch } from 'vue';
import provinceList from './data.json';

export default defineComponent({
  name: 'CitySelect',
  inheritAttrs: true,
  props: {
    /** 省份ID */
    province: { type: String, default: undefined },
    /** 对应市区ID */
    city: { type: String, default: undefined },
    /** 对应县区ID */
    district: { type: String, default: undefined },
    /** 加载动画 */
    loading: { type: Boolean, default: false },
    /** 不可编辑 */
    disabled: { type: Boolean, default: false },
    /** 支持清除 */
    allowClear: { type: Boolean, default: true },
    /** 省份下拉框属性 */
    provinceProps: { type: Object, default: undefined },
    /** 市下拉框 */
    cityProps: { type: Object, default: undefined },
    /** 县区下拉框 */
    districtProps: { type: Object, default: undefined }
  },
  // 数据的双向绑定事件不对外暴露
  emits: ['change', 'update:province', 'update:city', 'update:district'],
  setup(props, { emit }) {
    const state = reactive<{
      province?: string;
      city?: string;
      district?: string;
    }>({
      province: undefined,
      city: undefined,
      district: undefined
    });
    watch(
      [() => props.province, () => props.city, () => props.district],
      () => {
        state.province = props.province || undefined;
        state.city = (state.province && props.city) || undefined;
        state.district = (state.province && state.city && props.district) || undefined;
      },
      { immediate: true }
    );
    const cityList = computed(() => {
      if (!state.province) {
        return [];
      }
      const province = provinceList.find((item) => state.province === item.code);
      return province.city;
    });
    const districtList = computed(() => {
      if (!state.city || !state.province) {
        return [];
      }
      const province = provinceList.find((item) => state.province === item.code);
      const city = province.city.find((item) => state.city === item.code);
      return city.district;
    });

    const selectProvince = () => {
      state.city = undefined;
      state.district = undefined;
      emit('update:province', state.province);
      emit('update:city', state.city);
      emit('update:district', state.district);
      emitChange();
    };
    const selectCity = () => {
      state.district = undefined;
      emit('update:city', state.city);
      emit('update:district', state.district);
      emitChange();
    };
    const selectDistrict = () => {
      emit('update:district', state.district);
      emitChange();
    };
    const emitChange = () => {
      const dataName = {
        provinceName: '',
        cityName: '',
        districtName: ''
      };
      if (state.province) {
        const province = provinceList.find((item) => state.province === item.code);
        province && (dataName.provinceName = province.name);
        if (state.city) {
          const city = province.city.find((item) => state.city === item.code);
          city && (dataName.cityName = city.name);
          if (state.district) {
            const district = city.district.find((item) => state.district === item.code);
            district && (dataName.districtName = district.name);
          }
        }
      }
      emit('change', state, dataName);
    };
    return {
      state,
      cityList,
      provinceList,
      districtList,

      selectProvince,
      selectCity,
      selectDistrict
    };
  }
});
</script>

<style lang="less" scoped>
.city-select-row {
  display: inline;
  :deep(.ant-spin-container) {
    display: flex;
    flex-direction: row;
  }
  .item {
    width: calc(33.3% - 6px);
    max-width: 220px;
    margin-left: 9px;
    &:first-child {
      margin-left: 0;
    }
  }
}

@media screen and (max-width: @screen-sm) {
  .item:first-child {
    margin: 0;
    margin-bottom: 8px;
  }
}
</style>
